<?php

class HtmlControlParser extends CommonParser
{
	protected $self_tag;
	protected $html_tag;		//el nombre del tag que soy (div, img, table,...)
	protected $html_attrs;
	protected $id;				//el id del control (y nombre de la variable)
	
	/*
	Este constructor utiliza un tag info
	*/
	/*
	$tag tiene los campos
	tag:			el nombre del tag
	literal:		el contenido literal del tag de apertura
	inner_content:	todo lo que hay entre los tags de apertura y cierre
	outer_content:	Todo el contenido
	pos:			la posición en la que está el runat="server" dentro del innerhtml de su contenedor 
	tag_start:	la posición en la que empieza el tag de apertura (<)
	tag_end:		la posición en la que termina el tag de apertura (>)
	id:			el valor del atributo id (es obligatorio)
	short_tag:	bool que indica si el tag es autocontenido (<img src="xxxx" />)
	close_start:	la posición en la que empieza el tag de cierre
	close_end:	la posición en la que termina el tag de cierre	
	*/	
	function __construct($tag)
	{
		$this->self_tag = $tag;
		$this->content = $tag["outer_content"];
		$this->inner_content = $tag["inner_content"];
		$this->id = $tag["id"];
	}

	public function parse()
	{
		//global $debug_level;
		
		parent::parse();
		//ya tengo subparsers y tags
		
		$this->html_tag = $this->self_tag["tag"];
		$this->html_attrs = array();
		$attr_rex = "/\\b([a-zA-Z]\\w*?)\\=\"(.*?)\"[\\s\\n\\r\\f\\>]/s";
		preg_match_all($attr_rex, $this->self_tag["literal"], $matches);
		
		//para cada par atributo-valor encontrado
		for($i=0; $i<sizeof($matches[1]); $i++)
		{
			if($matches[1][$i]!="runat" && $matches[1][$i]!="id")
				$this->html_attrs[$matches[1][$i]] = $matches[2][$i];
		}
		
		if($debug_level>3) echo "HTML attrs de '".$this->id."': \n".print_r($this->html_attrs, true);
	}
	
	
	//CREO QUE ESTO YA NO VALE PARA NADA
	//esto funciona con arrays q. tienen una clave "start"
	static function sortByStartPos($a, $b)
	{
		if($a["start"]==$b["start"]) return 0;
		else return $a["start"]>$b["start"]?1:-1;
	}
	
	//esto construye el código que llamará el contenedor para crearlo.
	//en este caso, me puedo pasar $rootParser by the lining
	public function getInitCode($rootParser)
	{
		//global $debug_level;
		
		if($debug_level>0) echo "HtmlControlParser(".$this->id.")->getInitCode()\n";
		
		$wr = new CodeWriter();
		//crear código que construye htmlAttrs, tag, literal e innerContent
		//por una pruebilla que he hecho, es más barato deserializar que construir desde código
		
		//tengo que pasarle el inner_content partido en cachos, alternando su propio código fuente con llamadas a los render() de los hijos
		//preparo una lista de bloques de código, cada una con dos posiciones
		//[is_control] => indica si la pos corresponde a un bloque estático, o a un subcontrol
		//[code] => es el contenido estático o bien el id del control
		//como paso previo, ordeno los tags según su posición de apertura
		//¿tal vez esto no sea necesario debido a la naturaleza de find_server_tags?
		$parts = array();
		foreach($this->subparsers as $id=>$subparser)
		{
			$parts[] = array("id"=>$id, "start"=>$this->tags[$id]["tag_start"]);
		}
		usort($parts, array("HtmlControlParser", "sortByStartPos"));
		//lo que me interesa es que he obtenido los ids de subparsers ordenados por posición dentro del código fuente
		$blocks = array();
		$ix = 0;
		for($i=0; $i<sizeof($parts); $i++)
		{
			if($debug_level>1) echo "Vuelta $i, trabajo con '".$parts[$i]["id"]."'\n";
			if($debug_level>1) echo "TAGS: \n".print_r($this->tags,true);
			
			$siguiente_tag_cont = $this->tags[$parts[$i]["id"]]["outer_content"];			
			$siguiente_tag_pos = strpos($this->inner_content, $siguiente_tag_cont);
						
			$blocks[] = array("is_control"=>false, "code"=>substr($this->inner_content, $ix, $siguiente_tag_pos-$ix));
			$blocks[] = array("is_control"=>true, "code"=>$parts[$i]["id"]);
			
			$ix = $siguiente_tag_pos + strlen($siguiente_tag_cont);
		}
		$blocks[] = array("is_control"=>false, "code"=>substr($this->inner_content, $ix));
		if($debug_level>2) print_r($blocks);
		
		$wr->tabs();
		$wr->write("\$init_obj = array(");
		$wr->write("\"attrs\"=>unserialize(\"".encode_string(serialize($this->html_attrs))."\")");
		$wr->write(", \"tag\"=>\"".$this->html_tag."\"");
		$wr->write(", \"short_tag\"=>".($this->self_tag["short_tag"]?"true":"false"));
		$wr->write(", \"id\"=>\"".$this->id."\"");
		$wr->write(", \"tag_literal\"=>\"".encode_string($this->self_tag["literal"])."\"");
		//$wr->write(", \"inner_content\"=>\"".encode_string($this->self_tag["inner_content"])."\"");
		$wr->write(", \"inner_content\"=>unserialize(\"".encode_string(serialize($blocks))."\")");		
		$wr->write(", \"subcontrol_ids\"=>unserialize(\"".encode_string(serialize(array_keys($this->subparsers))).")\")");
		$wr->line(");");
		
		$wr->line("\$this->".$this->id." = new HtmlControl(\$init_obj, \$this);");
		$wr->line("\$this->registerControl(\$this->".$this->id.");");
		
		return $wr->toString();
	}
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
}

?>